<template>
    <div class="contract-container">
        <div class="tree">
            <div class="title">分类</div>
            <el-scrollbar max-height="calc(100% - 32px)">
                <el-tree style="max-width: 600px" :data="classify" :props="{ label: 'name', key: 'categoryId' }"
                    @current-change="checkClassify" />
            </el-scrollbar>
        </div>
        <div class="content">
            <div class="checked-classify">
                <span>{{ active.preview?.join(' > ') }}</span>
                <el-space>
                    <el-button type="primary" size="small" @click="addRemarkConfig">添加备注配置</el-button>
                    <el-button type="primary" plain size="small" @click="openPreview" v-if="data.length">预览</el-button>
                </el-space>
            </div>
            <el-scrollbar max-height="calc(100% - 32px)">
                <el-empty v-if="!data.length" description="暂无内容" />
                <template v-for="item, index in data" :key="item">
                    <div class="list-item">
                        <el-form ref="contractForm" :model="item" :disabled="editing != index" :rules="rules"
                            hide-required-asterisk>
                            <div class="name">
                                <div class="space">
                                    <el-form-item label="名称" prop="fieldName">
                                        <el-input placeholder="请输入" v-model="item.fieldName"></el-input>
                                    </el-form-item>
                                    <el-form-item prop="fieldType">
                                        <el-select style="width: 150px;" placeholder="选择属性类型" v-model="item.fieldType">
                                            <el-option v-for="item in dictOption.contract_extra_type"
                                                :label="item.dictLabel" :value="Number(item.dictValue)"></el-option>
                                        </el-select>
                                    </el-form-item>
                                    <el-form-item label="排序号" prop="sortNo">
                                        <el-input style="width: 80px;" v-model="item.sortNo"></el-input>
                                    </el-form-item>
                                    <el-form-item label="是否必填" prop="isRequired">
                                        <el-radio-group v-model="item.isRequired">
                                            <el-radio v-for="item in dictOption.contract_extra_is_required"
                                                :label="item.dictLabel" :value="Number(item.dictValue)"></el-radio>
                                        </el-radio-group>
                                    </el-form-item>
                                </div>
                                <div class="space operate-btn">
                                    <el-icon class="check" @click="save(index)" v-if="editing == index">
                                        <Check />
                                    </el-icon>
                                    <el-icon class="edit" v-else @click="editing = index">
                                        <Edit />
                                    </el-icon>
                                    <el-icon class="del" v-if="!item.options.length"
                                        @click="openDel({ tip: '备注配置', name: item.fieldName, contractExtraId: item.contractExtraId, index })">
                                        <Delete />
                                    </el-icon>
                                </div>
                            </div>
                        </el-form>
                        <div class="options">
                            <el-form :ref="'contractFormOption' + index" :model="option" :disabled="editing != index"
                                v-for="option, i in item.options" :rules="rules" hide-required-asterisk>
                                <div class="space">
                                    <el-form-item :label="`选项${i + 1}`" prop="optionName">
                                        <el-input v-model="option.optionName" />
                                    </el-form-item>
                                    <el-form-item label="排序号" prop="sortNo">
                                        <el-input style="width: 80px" v-model="option.sortNo" />
                                        <el-icon v-if="editing==index" @click="openDel({ name: option.optionName, tip: '选项配置', index, i })">
                                            <Delete />
                                        </el-icon>
                                    </el-form-item>
                                </div>
                            </el-form>
                            <el-space class="add" v-if="editing==index" @click="addOption(index)">
                                <el-icon>
                                    <CirclePlus />
                                </el-icon>
                                添加选项值
                            </el-space>
                        </div>
                    </div>
                </template>
            </el-scrollbar>
        </div>
        <el-dialog v-model="previewVisible" title="合同备注配置预览" width="400" align-center>
            <el-form label-width="auto">
                <template v-for="item in data" :key="item.contractExtraId">
                    <el-form-item :label="item.fieldName" v-if="item.options.length">
                        <el-select :multiple="item.fieldType == 2" v-model="preview[item.contractExtraId]">
                            <el-option v-for="option in item.options" :value="option.optionId" :key="option.optionId"
                                :label="option.optionName"></el-option>
                        </el-select>
                    </el-form-item>
                </template>
            </el-form>
        </el-dialog>
        <Modal v-model:visible="delVisible" :name="delItem.name" :tip="delItem.tip"
            @confirm="del(delItem.contractExtraId, delItem.index)">
        </Modal>
        <Modal v-model:visible="delOptionVisible" :name="delItem.name" :tip="delItem.tip"
            @confirm="deleteOption(delItem.index, delItem.i)">
        </Modal>
    </div>
</template>

<script setup>
import { getCategoryTree } from "@/api/products/manage";
import { onMounted, ref } from "vue";
import { getList, deleteContractExtra, saveContractExtra } from "@/api/products/contract";
import { getDicts } from "@/api/system/dict/data";
import { ElMessage } from "element-plus";
import Modal from "./components/Modal.vue";
const { proxy } = getCurrentInstance()

const contractForm = ref(null);
const editing = ref(null);
const data = ref([]);
const classify = ref([]);
const previewVisible = ref(false);
const preview = ref({});
const delVisible = ref(false);
const delItem = ref({});
const delOptionVisible = ref(false);
const temp = ref([]);
/**
 * 进入页面默认选择第一个分类下的第一个选项
 */
const getChild = (tree) => {
    let child = {}
    const traverse = (tree) => {
        if (!(tree.children && tree.children.length)) {
            child = tree;
        } else {
            traverse(tree.children[0]);
        };
    }
    traverse(tree);
    return child;
}
const childId = ref([])
const filterParent = (arr) => {
    arr.forEach((v) => {
        if (!v.children.length) {
            childId.value.push(v.categoryId);
        } else {
            filterParent(v.children);
        }
    });
};
const openDel = (item) => {
    if (editing.value != null && editing.value != item.index) return ElMessage.error('请先保存当前配置');
    let isOpen = true;
    if (item.tip == '备注配置') {
        item.name = item.name ? item.name : temp.value[item.index]?.fieldName;
        if (!item.name) {
            isOpen = false;
            del(item.contractExtraId, item.index)
        } else {
            delItem.value = { ...item };
            delVisible.value = isOpen;
        }
    } else if (item.tip == '选项配置') {
        item.name = item.name ? item.name : temp.value[item.index]?.options[item.i]?.optionName;
        if (!item.name) {
            isOpen = false;
            deleteOption(item.index, item.i);
        } else {
            delItem.value = { ...item };
            delOptionVisible.value = isOpen;
        }
    }
}
/**
 * 必填
 */
const required = { required: true, message: '请输入', trigger: 'blur' }
/**
 * 校验整数
 */
const verifyInt = (rule, value, callback) => {
    const regex = /^[1-9]\d*$/;
    if (!regex.test(value)) {
        callback(new Error('请输入正整数'))
    } else {
        callback()
    }
}
const openPreview = () => {
    if (editing.value != null) {
        return ElMessage.error('请先保存正在编辑的配置');
    }
    previewVisible.value = true;
}
const configVerif = (rule, value, callback) => {
    if (value.trim().length > 30) {
        callback(new Error('名称不能超过30个字符'))
    } else {
        callback()
    }
}
const optionVerif = (rule, value, callback) => {
    if (value.trim().length > 20) {
        callback(new Error('选项值不能超过20个字符'))
    } else if (data.value[editing.value].options.filter(v => v.optionName == value).length > 1) {
        callback(new Error('选项值不能重复'))
    } else {
        callback()
    }
}
/**
 * 校验规则
 */
const rules = {
    fieldName: [required, { validator: configVerif, trigger: 'blur' }],
    sortNo: [required, { validator: verifyInt, trigger: 'blur' }],
    fieldType: [{ required: true, message: '请选择', trigger: 'change' }],
    isRequired: [{ required: true, message: '请选择', trigger: 'change' }],
    optionName: [required, { validator: optionVerif, trigger: 'blur' }],
}
/**
 * 删除当前option项
 * @param {*} index 备注配置的下标
 * @param {*} i 当前备注配置的option下标
 */
const deleteOption = (index, i) => {
    if (editing.value != index && editing.value != null) return ElMessage.error('请先保存当前配置');
    editing.value = index;
    proxy.$refs['contractFormOption'+index][i].clearValidate()
    data.value[index]?.options.splice(i, 1);
    temp.value[index]?.options.splice(i, 1);
    ElMessage.success('删除成功，保存后生效');
    delOptionVisible.value = false;
}
/**
 * 删除备注配置 
 * @param {*} contractExtraId 备注配置的id
 * @param {*} index 备注配置的下标
 */
const del = async (contractExtraId, index) => {
    if (editing.value != index && editing.value != null) return ElMessage.error('请先保存当前配置');
    if (!contractExtraId) {
        data.value.splice(index, 1);
        editing.value = null;
        return ElMessage.success('删除成功');
    }
    const res = await deleteContractExtra({ contractExtraIds: [contractExtraId] });
    if (res.code == 200) {
        ElMessage.success("删除成功");
        delVisible.value = false;
        editing.value = null;
        init()
    }
}
const addOption = (index) => {
    if (editing.value != null && editing.value != index) return ElMessage.error('请先保存当前配置');
    editing.value = index;
    data.value[index].options.push({ sortNo: 1 });
}
/**
 * 添加备注配置
 */
const addRemarkConfig = () => {
    if (editing.value != null) {
        return ElMessage.error('请先保存正在编辑的配置');
    }
    data.value.push({ options: [], isRequired: 1, sortNo: 1 });
    editing.value = data.value.length - 1;
}
const dictOption = ref({})
const getClassify = async () => {
    const res = await getCategoryTree();
    classify.value = res.data;
    filterParent(res.data);
    checkClassify(getChild(res.data[0]));
    init()
}
/**
 * 保存
 */
const save = (index) => {
    const confirm = async () => {
        const res = await saveContractExtra({
            categoryId: active.value.fomart[active.value.fomart.length - 1],
            fieldInfo: data.value[index]
        })
        if (res.code == 200) {
            editing.value = null;
            ElMessage.success('保存成功');
            init()
        }
    }

    contractForm.value[index].validate(async (value) => {
        if (value) {
            if (!data.value[index].options?.length) {
                confirm()
            } else {
                let arr = [];
                proxy.$refs['contractFormOption'+index].forEach((v) => {
                    arr.push(new Promise((resolve) => {
                        v.validate((valid) => {
                            resolve(valid);
                        });
                    }))
                })
                const res = await Promise.all(arr);
                if (res.length && res.every(v => v)) {
                    confirm()
                }
            }
        }
    })
}
const active = ref({})
const checkClassify = (value) => {
    if (childId.value.includes(value.fomart.split('-')[value.fomart.split('-').length - 1])) {
        active.value = {
            preview: value.preview.split('-'),
            fomart: value.fomart.split('-'),
        }
        init()
    }
}
const init = async () => {
    const res = await getList(active.value.fomart[active.value.fomart.length - 1]);
    data.value = res.data;
    temp.value = JSON.parse(JSON.stringify(res.data));
}
const getDict = async (dict) => {
    const res = await getDicts(dict);
    dictOption.value[dict] = res.data;
}
onMounted(() => {
    const dictArr = ['contract_extra_is_required', 'contract_extra_type'];
    dictArr.forEach(v => {
        getDict(v)
    })
    getClassify();
})
</script>

<style lang="scss" scoped>
@mixin padding {
    padding: 0 20px;
}

.contract-container {
    padding: 20px;
    box-sizing: border-box;
    display: flex;
    gap: 20px;

    >div {
        background: white;
        height: calc(100vh - 126px);
        box-shadow: 4px 5px 16px 0px rgba(4, 19, 74, 0.04);
    }

    .tree {
        width: 300px;

        .title {
            margin-bottom: 20px;
        }
    }

    .content {
        flex: 1;
        padding: 20px;

        .checked-classify {
            @include padding;
            background: #F5F7FA;
            height: 40px;
            font-size: 14px;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        .list-item {
            background: #F5F7FA;
            padding-bottom: 1px;

            .space {
                height: 100%;
                display: flex;
                gap: 20px;
                align-items: center;
            }

            .name {
                @include padding;
                display: flex;
                justify-content: space-between;
                align-items: center;
                height: 73px;
                margin-top: 20px;
                border-bottom: 1px solid #DCDFE6;


                >.space:first-child {
                    align-items: end;
                }

                .operate-btn {
                    .el-icon {
                        color: rgb(144, 147, 153)
                    }

                    .check {
                        color: rgb(20, 200, 92)
                    }

                }
            }

            .options {
                margin: 20px;
                background: white;
                padding: 20px;

                ::v-deep(label) {
                    font-weight: unset;
                }

                .space {
                    .el-icon {
                        margin-left: 8px;
                        color: rgb(144, 147, 153)
                    }
                }
            }

            .add {
                color: #007DFF;
                font-size: 14px;
                cursor: pointer;
            }

            .remark {
                @include padding;
            }
        }
    }
}
</style>